#include "socket_stream.h"
#include "qtch/log.h"

namespace qtch{
static Logger::ptr logger =QTCH_LOG_NAME("system");

SocketStream::SocketStream(Socket::ptr sock,bool owner) 
        :m_socket(sock)
        ,m_owner(owner){
}

SocketStream::~SocketStream() {
    if(m_owner && m_socket){
        m_socket->close();
    }
}

int SocketStream::read(void* buffer, size_t length) {
    if(!isConnected()){
        return -1;
    }
    int rt = m_socket->recv(buffer,length);
    QTCH_LOG_DEBUG(logger) << "fd:" << m_socket->getSocket()
        << " rt=" << rt
        << " read:[" << ((rt == -1) ? "" : std::string((char*)buffer,rt)) << "]";
    return rt;
}

int SocketStream::read(ByteArray::ptr ba,size_t length) {
    if(!isConnected()){
        return -1;
    }
    std::vector<iovec> iovs;
    ba->getWriteBuffer(iovs,length);
    int rt = m_socket->recv(&iovs[0],iovs.size());
    if(rt>0){
        ba->setWritePosition(ba->getWritePosition() + rt);
    }
    return rt;
}

int SocketStream::write(const void* buffer, size_t length) {
    if(!isConnected()){
        return -1;
    }
    return m_socket->send(buffer,length);
}

int SocketStream::write(ByteArray::ptr ba,size_t length) {
    if(!isConnected()){
        return -1;
    }
    std::vector<iovec> iovs;
    ba->getReadBuffer(iovs,length);
    int rt = m_socket->send(&iovs[0],iovs.size());
    if(rt>0){
        ba->setReadPosition(ba->getReadPosition() + rt);
    }
    return rt;
}

void SocketStream::close() {
    if(m_socket){
        m_socket->close();
    }
}


bool SocketStream::isConnected() const{
    return m_socket ? m_socket->isConnected() : false;
}

Address::ptr SocketStream::getRemoteAddress() {
    return m_socket ? m_socket->getRemoteAddress() : nullptr;
}

Address::ptr SocketStream::getLocalAddress() {
    return m_socket ? m_socket->getLocalAddress() : nullptr;
}

std::string SocketStream::getRemoteAddressString() {
    auto addr = getRemoteAddress();
    if(addr){
        return addr->toString();
    }
    return "";
}

std::string SocketStream::getLocalAddressString() {
    auto addr = getLocalAddress();
    if(addr){
        return addr->toString();
    }
    return "";
}


}